package com.sergio.compress.service;

import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.sergio.compress.dao.model.SeTestRecord;
import com.sergio.compress.dao.service.SeTestRecordService;
import com.sergio.compress.model.base.TestDataBase;
import com.sergio.compress.model.base.TestDataChildBase;
import com.sergio.compress.model.base.TestDataWrapperBase;
import com.sergio.compress.model.channelWapper.*;
import com.sergio.compress.model.proto.Gift;
import com.sergio.compress.model.type1.*;
import com.sergio.compress.utils.CommonUtil;
import com.sergio.compress.utils.TransUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

import static com.sergio.compress.utils.CommonUtil.generateRandomString;

/**
 * @Author : Sergio.D
 * @Description :
 * @CreateDate ：2023/6/15 19:00
 */
@Service
public class SeTestService {


    @Autowired
    SeTestRecordService seTestRecordService;

    private static boolean needSave = false;
    private static final Random random = new Random();

    public static long batchNum = 1;

    public void makeTest(List<TestDataBase> dataSource, int lengthSourceSe) {
//        saveSeTestResult(new ProtoWrapper().doTest(dataSource, lengthSourceSe), needSave);
////        saveSeTestResult(new JacksonProtoWrapper().doTest(dataSource, lengthSourceSe), needSave);
//        saveSeTestResult(new JacksonCBORWrapper().doTest(dataSource, lengthSourceSe), needSave);
//        saveSeTestResult(new JacksonAvroWrapper().doTest(dataSource, lengthSourceSe), needSave);
////        saveSeTestResult(new IONWrapper().doTest(dataSource, lengthSourceSe), needSave);
//        saveSeTestResult(new JacksonIONWrapper().doTest(dataSource, lengthSourceSe), needSave);
//        saveSeTestResult(new JSONWrapper().doTest(dataSource, lengthSourceSe), needSave);
//        saveSeTestResult(new HessianWrapper().doTest(dataSource, lengthSourceSe), needSave);
//        saveSeTestResult(new JacksonMsgpackWrapper().doTest(dataSource, lengthSourceSe), needSave);
//        saveSeTestResult(new JacksonBSONWrapper().doTest(dataSource, lengthSourceSe), needSave);

        TestDataWrapperBase dataSend = new TestDataWrapperBase(dataSource);

        List<Gift.TestData> dataContent = TransUtil.convertToProto(dataSource);
        Gift.TestDataList.Builder listBuilder = Gift.TestDataList.newBuilder();
        listBuilder.addAllData(dataContent);
        saveSeTestResult(new Proto1().doTest(listBuilder.build(), lengthSourceSe), needSave);


        saveSeTestResult(new CBOR1().doTest(dataSend, lengthSourceSe), needSave);
        saveSeTestResult(new Avro1().doTest(dataSend, lengthSourceSe), needSave);
        saveSeTestResult(new ION1().doTest(dataSend, lengthSourceSe), needSave);
        saveSeTestResult(new JSON1().doTest(dataSend, lengthSourceSe), needSave);
        saveSeTestResult(new Hessian1().doTest(dataSend, lengthSourceSe), needSave);
        saveSeTestResult(new MsgPack1().doTest(dataSend, lengthSourceSe), needSave);
        saveSeTestResult(new BSON1().doTest(dataSend, lengthSourceSe), needSave);
        //跳过第一次  防止冷启动之类的出现较大的数据 拉高图表
        this.needSave = true;
    }


    public List<TestDataBase> makeData(int num) {
        List<TestDataBase> result = new LinkedList<>();
        int i = 0;
        while (i < num) {
            result.add(makeData());
            i++;
        }
        return result;
    }

    private TestDataBase makeData() {
        List<String> receiverUserIds = new ArrayList<>();
        List<TestDataChildBase> child = new ArrayList<>();
        TestDataBase testData = new TestDataBase();
        testData.setPrepareId(generateRandomString(10));
        testData.setRoomId(generateRandomString(random.nextInt(100)));
        testData.setGoodsId(random.nextInt(100));
        testData.setGoodsQuantity(random.nextInt(100));
        testData.setName(generateRandomString(10));
        testData.setChannelId(random.nextInt(100));
        testData.setPresenterUserId(generateRandomString(10));
        testData.setPresentAt(new Date()); // set the presentAt field to the current date and time
        testData.setAcquireFortuneQuantity(random.nextInt(100));
        testData.setAcquirePopQuantity(random.nextInt(100));
        int size1 = random.nextInt(5);
        for (int i = 1; i <= size1; i++) {
            receiverUserIds.add(generateRandomString(10));
        }
        testData.setReceiverUserIds(receiverUserIds);
        int size2 = random.nextInt(5);
        for (int i = 1; i <= size2; i++) {
            TestDataChildBase testDataChild = new TestDataChildBase();
            testDataChild.setName(generateRandomString(5));
            testDataChild.setUserId(random.nextInt(100));
            child.add(testDataChild);
        }
        testData.setChild(child);
        return testData;
    }


    /**
     * @param minInfoLength  起始的用户个数
     * @param maxByteLength  最大字节长度   以protobuf为基准 当他序列化超过改长度后则终止
     * @param stepInfoLength 每次增加的用户个数
     */
    public void makeTest(int minInfoLength, int maxByteLength, int stepInfoLength) {
        List<TestDataBase> testSource = makeData(minInfoLength);
        int lengthSourceSe = 0;
        do {
            List<TestDataBase> add = makeData(stepInfoLength);
            testSource.addAll(add);
            try {
                JsonMapper mapper = new JsonMapper();
                mapper.registerModule(new JavaTimeModule());
                byte[] cborData = mapper.writeValueAsBytes(testSource);
                lengthSourceSe = cborData.length;
                makeTest(testSource, lengthSourceSe);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } while (lengthSourceSe < maxByteLength);
    }

    public void addBatchNum() {
        batchNum++;
    }


    public void saveSeTestResult(List<SeTestRecord> seTestRecord, boolean needSave) {
        if (needSave) {
            for (SeTestRecord seTestRecord1 : seTestRecord) {
                saveSeTestResult(seTestRecord1);
            }

        }

    }

    public void saveSeTestResult(SeTestRecord seTestRecord) {
        seTestRecord.setBatchNum(batchNum);
        seTestRecordService.save(seTestRecord);
    }

}
